﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Net;
using System.Net.Sockets;
using System.Threading;


namespace server
{
    public class Client
    {
        //Sockets routine
        Form1 ParentForm;
        Socket ClientSocket;
        public string ClientName = "";
        //threads
        Thread MessageLoopThread;

        //Queue emplementation
        public Queue<string> Queue = new Queue<string>();
        //States and messages
        string okAnswer = "ok";
        string emptyAnswer = "empty";
        int tryOutCount = 10;//number of tryouts on bad response
        int tryOuts;
        bool Connected = false;
        public int ID;
        //
        public Client(Socket inputSocket, Form1 _parentForm,string name)
        {
            ParentForm = _parentForm;
            ClientSocket = inputSocket;
            ClientName = name;
            MessageLoopThread = new Thread(new ThreadStart(ClientListen));
            MessageLoopThread.Start();
        }

        public void SendMessage(string msg)
        {
            Queue.Enqueue("message|"+msg);
        }

        void ConsoleWrite(string msg)
        {
            ParentForm.ConsoleWrite(msg);
        }

        //================
        void EnterMessageLoop()
        {
            if(ClientSocket.Connected==true)
            while (true)
            {
                //
                string Message = ReceivePacket();

                if(Message =="disconnect"){
                    Disconnect();
                }
                
                    if (Message == emptyAnswer)
                    {

                        string message;

                        if (Queue.Count <= 0)//if queue is empty
                        {
                            message = okAnswer;//send ok message
                        }
                        else
                        {
                            message = Queue.Dequeue();//or send message in queue

                            ConsoleWrite("Message send: " + message + "\n");
                        }

                        SendPacket(message);

                    }
                    else
                    {

                        string[] MessageSplit = Message.Split(new Char[] { '|' });
                        //ConsoleWrite("Recieived some message!");
                        if (MessageSplit[0] == "message")
                        {
                            //DisplayMessage("this is message from server!");
                            ConsoleWrite(ClientName + ": ");
                            ConsoleWrite(MessageSplit[1] + "\n");
                        }
                        SendPacket(okAnswer);
                    }
                


            }
        }

        public void Disconnect()
        {
            //SendPacket("disconnect");
            //Queue.Enqueue("disconnect");
            ConsoleWrite("Client disconnected\n");
            Connected = false;
            SendPacket("disconnect");
            MessageLoopThread.Abort();
        }

        public void SendPacket(string msg)
        {
            try
            {
                byte[] data = new byte[4096];
                data = Encoding.UTF8.GetBytes(msg);
                ClientSocket.Send(data, data.Length,
                         SocketFlags.None);
                tryOuts = 0;
            }
            catch
            {
                ConsoleWrite("SendPacket error\n");
                tryOuts++;
                if (tryOuts >= tryOutCount) Disconnect();
            }
        }

        public string ReceivePacket()
        {
            try
            {
                byte[] receiveMessage = new byte[4096];
                int recmsg = ClientSocket.Receive(receiveMessage);
                string Message = Encoding.UTF8.GetString(receiveMessage, 0, recmsg);
                tryOuts = 0;
                return Message;
            }
            catch
            {
                ConsoleWrite("ReceivePacket error\n");
                tryOuts++;
                if (tryOuts >= tryOutCount) Disconnect();
                return null;
            }
        }


        void ClientListen()
        {
            while(true){//messages loop with client on socket
                //Thread.Sleep(500);
                
                
                ConsoleWrite("Waiting for answer...\n");
                string stringData;

                stringData = ReceivePacket();
                ConsoleWrite(stringData);

                if (stringData == "welcomeclient")
                {
                    ConsoleWrite("Welcome from client recieved\n");
                    string serverok;

                    serverok = "serverok";

                    SendPacket(serverok);
                    ConsoleWrite("client connected succesful\n");
                    //connected, go to messageloop
                    Connected = true;
                    EnterMessageLoop();
                }
            }
        }




    }
}
